package com.qxbb.report.utils;

import com.baomidou.mybatisplus.core.toolkit.Assert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;


/**
 * DES加密工具类
 */
@Slf4j
public class DesUtil {

    /**
     * 数据同前端保持一致
     */
    //密钥
    private static final String secretKey = "54367819";
    //偏移量
    private static final String ivHex = "54367819";

    private static final String DES_KEY = "3955C482C8C85B4CA8C9D8D4987F8B7F";
	private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding";
    private static final String DES = "DES";

        public static String encryptCBC(String data) {
            if (data == null){
                return null;
            }
            try {
                byte[] encoded = secretKey.getBytes(StandardCharsets.UTF_8);
                // 生成密钥字符串
//              String encodeHexString = byte2hex(encoded);
                String encodeHexString = Hex.encodeHexString(encoded);
                // 再把我们的字符串转变为字节数组，可以用于另一方使用，验证
                byte[] decodeHex = Hex.decodeHex(encodeHexString.toCharArray());
                // 生成密钥对象
                SecretKeySpec secretKeySpec = new SecretKeySpec(decodeHex, "DES");
                Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
                IvParameterSpec iv = new IvParameterSpec(ivHex.getBytes(StandardCharsets.UTF_8));
                cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, iv);
                byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
                return byte2hex(encrypted); //此处2次加密
            } catch (Exception e) {
               log.error("e.printStackTrace()",e);
                return data;
            }
        }
	public static String decryptCBC(String data) {
		if (data == null) {
			return null;
		}
		try {
			byte[] src = hex2byte(data);
			IvParameterSpec iv = new IvParameterSpec(ivHex.getBytes(StandardCharsets.UTF_8));
			Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
			DESKeySpec dks = new DESKeySpec(secretKey.getBytes(StandardCharsets.UTF_8));
			SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
			SecretKey secretKey = keyFactory.generateSecret(dks);
			cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
			return new String(cipher.doFinal(src));
		} catch (Exception e) {
			log.error("解密失败", e);
			return data;
		}
	}
    /**
     * 加密 使用默认密钥
     *
     * @param src 数据源
     * @return 返回加密后的数据
     */
    public static String encrypt(String src) {
        cn.hutool.core.lang.Assert.notEmpty(src, "param src can not be empty");

        try {
            return byte2hex(encrypt(src.getBytes(), DES_KEY.getBytes()));
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }

        return null;
    }

    public static String byte2hex(byte[] bytes) {
        Assert.notNull(bytes, "param bytes can not be null");

        StringBuilder hs = new StringBuilder();
        String stmp = "";
        for (byte b : bytes) {
            stmp = (Integer.toHexString(b & 0XFF));
            if (stmp.length() == 1) {
                hs.append("0").append(stmp);
            } else {
                hs.append(stmp);
            }
        }
        return hs.toString().toLowerCase();
    }


    public static void main(String[] args) {
        String str = "42";
        System.out.println(encryptCBC(str));
        System.out.println("=============");

    }

    /**
     * 解密 使用默认密钥
     *
     * @param src 数据源
     * @return 返回解密后的数据
     */
    public static String decrypt(String src) {
        cn.hutool.core.lang.Assert.notEmpty(src, "param src can not be empty");
        try {
            return new String(decrypt(hex2byte(src), DES_KEY.getBytes()), StandardCharsets.UTF_8);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }

        return null;
    }

    /**
     * 解密
     *
     * @param src 数据源
     * @param key 密钥，长度必须是8的倍数
     * @return 返回解密后的原始数据
     * @throws Exception 异常
     */
    public static byte[] decrypt(byte[] src, byte[] key) throws Exception {
        SecureRandom sr = new SecureRandom();
        DESKeySpec dks = new DESKeySpec(key);

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey secretKey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance(DES);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, sr);

        return cipher.doFinal(src);
    }

    /**
     * 字符串转二进制
     *
     * @param str 字符串
     * @return 二进制
     */
    public static byte[] hex2byte(String str) {
        cn.hutool.core.lang.Assert.notEmpty(str, "param str can not be empty");

        byte[] bytes = str.getBytes();
        if ((bytes.length % 2) != 0) {
            throw new IllegalArgumentException("长度不是偶数");
        }
        byte[] b2 = new byte[bytes.length / 2];
        for (int n = 0; n < bytes.length; n += 2) {
            String item = new String(bytes, n, 2);
            b2[n / 2] = (byte) Integer.parseInt(item, 16);
        }
        return b2;
    }

    /**
     * 加密
     *
     * @param src 数据源
     * @param key 密钥，长度必须是8的倍数
     * @return 返回加密后的数据
     * @throws Exception 异常
     */
    public static byte[] encrypt(byte[] src, byte[] key) throws Exception {
        SecureRandom sr = new SecureRandom();
        DESKeySpec dks = new DESKeySpec(key);

        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey secretKey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance(DES);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr);
        return cipher.doFinal(src);
    }
}
